perm filename GCREF.FAI[SYS,HE] blob sn#084253 filedate 1974-01-28 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00020 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002		TITLE	GCREF - MULTI FILE CREF LISTINGS
C00005 00003	GET THE COMMAND LINE AND PUT INTO THE COMMAND BUFFER
C00009 00004	 PROCESS A SWITCH IF / IS BREAK CHARACTER
C00012 00005	 NOW WE HAVE FINISHED SCANNING COMMAND LINE
C00014 00006	 FIND CORRECT PAGE OF FILE
C00017 00007	 HAVING FOUND CORRECT PAGE, SCAN IT AND BUILD DATA STRUCTURE
C00020 00008	 KEEP ON BUILDING STRUCTURE
C00023 00009	 END OF STRUCTURE BUILDING - NOW WE OUTPUT IT
C00025 00010	 RECURSIVE OUTPUT ROUTINE
C00029 00011	 GET ONE PART OF FILE SPECS
C00031 00012	 MAGIC DECIMAL CONVERSION ROUTINE 
C00033 00013	 STRING EQUALITY TEST
C00035 00014	 CREATE A NEW IDENTIFIER BLOCK
C00037 00015	 THIS IS THE MAGIC 6-STATE, TABLE DRIVEN, INPUT PARSER
C00040 00016	 MORE BRANCHES FOR INPUT SCANNER
C00042 00017	 STILL MORE BRANCHES
C00043 00018	 PRIMARY TABLE FOR INPUT SCANNER
C00045 00019	 MORE SECONDARY TABLES
C00047 00020	 FINISH WITH SOME VARIABLES
C00049 ENDMK
C⊗;
	TITLE	GCREF - MULTI FILE CREF LISTINGS
EXTERNAL JOBREL,JOBFF

P←17
PT←16;		CURRENT LINK POINTER
ST←15;		STATE
FR←14;		FREE STORAGE POINTER
CONV←13;	ARGUMENT FOR CONVRT
TA←12;		T AND TA MUST BE CONSECUTIVE
T←11
NEW←10;		POINTER TO NEW BLOCK
INP←7;		INPUT POINTER
NBUF←4;		# OF I/O BUFFERS
PLEN←40;	LENGTH OF STACK

;FIRST WE INITIALIZE THE WORLD EVERYTIME WE START A NEW COMMAND

	SKIPE SVJOB
	JRST [	MOVE SVJOB		;THIS CORE IMAGE ALREADY RAN
		MOVEM JOBFF		;RESTORE JOBFF
		JRST GCREF]
	MOVE JOBFF			;OTHERWISE,
	MOVEM SVJOB#			;SAVE JOBFF FOR INITIALIZATION
GCREF:	MOVE P,[IOWD PLEN,PDL]		;INIT STACK
	SETZM SHORT			;INIT FLAGS - SHORT LISTING
	SETZM GLBAL			;	GLOBALS ONLY
	SETZM LOCAL			;	LOCALS ONLY
	SETZM OUTPNT			;INIT POINTERS - DEFAULT OUTPUT FILE
	SETZM INPNT			;	START OF INPUT FILES
	HRRZ FR,JOBFF			;	START OF FREE STORAGE-1
	SETZM STRUCT			;	START OF DATA STRUCTURE
	SETZM DEFPPN
	HRLZI 'CRF'
	MOVEM DEFEXT
	SETZM ERROR			; ERROR FLAG
	MOVE 1,JOBREL			; START WITH 1K OF FREE CORE
	ADDI 1,2000
	CALLI 1,11
	JRST NOCORE
	INIT 1,				; OPEN DISK
	SIXBIT .DSK.
	XWD OBUF,IBUF
	JRST [ OUTSTR [ASCIZ . NO DISK.]
	       CALLI 12]
	OUTSTR CRLF
	OUTCHR ["*"]			;TELL HIM WE ARE READY
;GET THE COMMAND LINE AND PUT INTO THE COMMAND BUFFER

COMGET:	MOVE 1,COMPNT			; READ LINE INTO COMMAND BUFFER
	INCHWL 2
	IDPB 2,1
	CAIE 2,15			; UNTIL CARRIAGE RETURN
	JRST .-3
	SETZM 2				;CONVERT TO ASCIZ
	IDPB 2,1
	CLRBFI				;FLUSH LINE FEED FROM BUFFER

; SCAN COMMAND LINE FOR FILE NAME OR SWITCH
	
	MOVE 1,COMPNT
	SETZM 4
GETFIL:	SETZM NAME
	SETZM PT			;  NO NAME YET
	MOVE 2,[POINT 7,NAME]		;  GET NEXT FILE SPECS
	PUSHJ P,GETPAR			;	LOOK FOR FILE NAME
	SKIPN SNAM
	JRST ENDPPN			;       IF NONE, MAYBE SWITCH
	PUSH FR,SNAM
	MOVEI PT,(FR)
	CAIE 4,"."
	JRST [PUSH FR,DEFEXT		;	NO EXTENSION GIVEN
	      JRST ENDEXT]
	IDPB 4,2
	PUSHJ P,GETPAR			;   	LOOK FOR EXTENSION
	PUSH FR,SNAM
	MOVE SNAM
	TRNE 777777
	JRST SPCERR			;	EXTENSION TOO LONG
	MOVEM DEFEXT			;	NEW DEFAULT
ENDEXT:	PUSH FR,[0]			;	THIS IS A LOOKUP BLOCK
	CAIE 4,"["
	JRST [PUSH FR,DEFPPN		;	NO PPN GIVEN
	      JRST ENDPPN]
	IDPB 4,2
	PUSHJ P,GETPAR			;	GET PPN
	SKIPN 6,SNAM
	JRST SPCERR
	TLNN 6,77			;	RIGHT ADJUSTED
	JRST [LSH 6,-6
	      JRST .-1]
	PUSH FR,6
	HLLM 6,DEFPPN
	CAIE 4,","
	JRST SPCERR
	IDPB 4,2
	PUSHJ P,GETPAR			;	GET REST OF PPN
	SKIPN 6,SNAM
	JRST SPCERR
	TLNN 6,77			;	ALSO RIGHT ADJUSTED
	JRST [LSH 6,-6
	      JRST .-1]
	HLRM 6,(FR)
	HLRM 6,DEFPPN
	IDPB 4,2
	CAIN 4,"]"
	JRST [	ILDB 4,1		; GET NEXT BREAK CHARACTER
		JRST ENDPPN]
SPCERR:	OUTSTR CRLF
	OUTSTR [ASCIZ .ILLEGAL FILE SPECIFICATION .]
	OUTSTR NAME
IGLOUT:	OUTSTR CRLF
	JRST GCLOOP
; PROCESS A SWITCH IF / IS BREAK CHARACTER

ENDPPN:	CAIE 4,"/"			; SWITCH COMING UP
	JRST L2
	ILDB 4,1
	CAIN 4,"L"
	JRST [SETOM LOCAL		; OUTPUT ONLY LOCALS
	      JRST LAB1]
	CAIN 4,"S"
	JRST [SETOM SHORT		; SHORT LISTING REQUESTED
	      JRST LAB1]
	CAIN 4,"G"
	JRST [SETOM GLBAL		; OUTPUT ONLY GLOBALS
LAB1:	      ILDB 4,1			;GET A NEW BREAK CHAR TO DECODE
	      JRST ENDPPN]
	OUTSTR CRLF
	OUTSTR [ASCIZ .ILLEGAL SWITCH - .]
IGLCHR:	OUTCHR 4
	JRST IGLOUT

; STORE FILE NAME FOR INPUT OR OUTPUT, AS BREAK CHAR INDICATES

L2:	SKIPN PT			;ONLY IF WE HAVE A FILE NAME
	JRST GETFIL
	CAIE 4,"←"
	JRST L1
	SKIPN INPNT			;OUTPUT FILE - ERROR IF INPUT FILE
	SKIPE OUTPNT			; ALREADY EXISTS OR
	JRST IGLBRK			; ALREADY HAVE AN OUTPUT FILE
	MOVEM PT,OUTPNT			; OTHERWISE, STORE POINTER TO BLOCK
	JRST GETFIL	

; WE HAVE ANOTHER INPUT FILE TO STORE IN LIST

L1:	SKIPN INPNT			; INIT POINTER IF FIRST BLOCK
	MOVEM PT,INPNT			; NEW INPUT FILE SPEC FOUND
	PUSHJ P,LOOKFL			; MAKE SURE FILE EXISTS
	CLOSE 1,			; BUT THEN LET GO OF IT FOR NOW
	CAIN 4,","
	JRST GETFIL			; RETURN FOR NEXT FILE SPEC
	CAIN 4,"→"
	JRST	[OUTSTR CRLF
		OUTCHR ["→"]
		JRST COMGET]		; MULTI LINE COMMAND
	CAIN 4,15
	JRST ENDCOM			; END OF COMMAND SCANNING
IGLBRK:	OUTSTR CRLF
	OUTSTR [ASCIZ .ILLEGAL CHARACTER - .]
	JRST IGLCHR
; NOW WE HAVE FINISHED SCANNING COMMAND LINE
; LOOKUP EACH FILE 

ENDCOM:	PUSH FR,[0]			; TO STOP FILE LOOKUPS
	SKIPE INPNT
	SKIPE ERROR
	JRST COMGET			; NO INPUT FILES OR ERROR
	MOVE INPNT
	MOVEM NXTPNT#			; NEXT INPUT FILE
	MOVEI 1,(FR)			; SET UP IOWD FOR FREE POINTER
	SUB FR,JOBREL
	HRLI FR,(FR)
	HRRI FR,(1)
LOOP:	MOVE 1,NXTPNT			;START LOOP TO INPUT FILES
	SKIPN 2,(1)			; IF ZERO - END OF FILES
	JRST ENDFIL
	LOOKUP 1,(1)			; LOOKUP NEXT FILE
	HALT				; ALREADY CHECKED THIS
	MOVEI 4(1)			; UPDATE POINTER TO NEXT FILE
	MOVEM NXTPNT
	MOVEI BUFRS			; GET SOME BUFFERS
	MOVEM JOBFF
	INBUF 1,NBUF
	INPUT 1,			; AND SOME DATA
	MOVE 3,[POINT 7,NAME+1]		; CONVERT FILE NAME TO ASCIZ
	SETZM NAME
	SETZM 1
	LSHC 1,6
	JUMPE 1,.+5
	MOVEI 1,40(1)
	IDPB 1,3
	AOS NAME
	JRST .-6
	IDPB 1,3
	OUTSTR CRLF			; LET USER KNOW WE ARE WORKING
	OUTSTR NAME+1
P11:	MOVEI 1,=30*5			; GET FIRST LINE OF PAGE
	MOVE 2,COMPNT
P10:	PUSHJ P,GCHAR
	IDPB CONV,2
	CAIN CONV,12
	JRST P2
	CAIN CONV,14
	JRST P11
	SOJG 1,P10
	JRST TSTFAL			; LINE TOO LONG
P2:	SETZM ST			;SCAN LINE AND TEST IF RIGHT PAGE
	MOVE [ILDB CONV,INP]		; SET PARSER TO READ CURRENT LINE
	MOVEM GET
	SETZM SVBRK
	MOVE INP,COMPNT
	SETZM CCNT
; FIND CORRECT PAGE OF FILE

	SETZM FID
P1:	SETZM ID
	PUSHJ P,PARSE			; PARSE INPUT
	MOVE 1,ID			; GET COUNT
	MOVE 2,ID+1			; AND FIRST WORD OF IDENTIFIER
	CAIN 1,4
	JRST	[XOR 2,[ASCII .FAIL.]	; COUNT=4
		ANDCMI 2,17		; TEST FAILS IF ID='FAIL' OR 'SAIL'
		JUMPE 2,TSTFAL
		MOVE 2,ID+1
		XOR 2,[ASCII .SAIL.]
		ANDCMI 2,17
		JUMPE 2,TSTFAL
		JRST P1]
	CAIN 1,5
	JRST	[XOR 2,[ASCII .MACRO.]	; COUNT=5
		JUMPE 2,TSTFAL		; TEST FAILS IF ID='MACRO'
		JRST P1]
	CAIE 1,7
	JRST P1				; NOT A RECOGNIZED ID, SCAN FURTHER
	XOR 2,[ASCII .PROGR.]		; COUNT=7
	JUMPN 2,P1			; TEST FAILS IF ID='PROGRAM'
	MOVE 2,ID+2
	XOR 2,[ASCII .AM.]
	AND 2,[XWD 17,-1]
	JUMPN 2,P1
TSTFAL:	MOVEI ST,1			;NOT CORRECT PAGE
	MOVE P10
	MOVEM GET
	SETZM SVBRK
	PUSHJ P,PARSE			;SCAN TO NEXT PAGE
	JRST P11			; AND TEST IT

; DATA STRUCTURE IS AS FOLLOWS:
;	WORD 1	LH: POINTER TO LAST BLOCK - 0 IF FIRST BLOCK OF LIST
;		RH: POINTER TO NEXT BLOCK - 0 IF LAST BLOCK OF LIST
;	WORD 2	LH: POINTER TO FIRST BLOCK ON LOWER STRUCTURE (0 IF LOWEST
;			LEVEL)
;		RH: WORD COUNT FOR DATA
;	REST	DATA: IF IDENTIFIER, CHARACTER COUNT FOLLOWED BY ASCIZ
;			STRING; IF LINE NUMBERS, DIGITS
;			STORED TWO TO A WORD (0 IN UNUSED HALVES) AND
;			NEGATED IF THIS IS THE IDENTIFIER DEFINITION
;
;	TOP LEVEL ARE IDENTIFIERS USED IN PROGRAM
;	NEXT LEVEL, FOR EACH IDENTIFIER, IS THE NAMES OF THE FILES
;		CONTAINING THE IDENTIFIER
;	NEXT LEVEL, IF ANY, IS THE NAMES OF THE BLOCKS WITHIN WHICH THE
;		IDENTIFIER WAS DEFINED
;	BOTTOM LEVEL IS LIST OF LINE NUMBERS
; HAVING FOUND CORRECT PAGE, SCAN IT AND BUILD DATA STRUCTURE

TSTOK:	MOVE [ILDB CONV,INP]		;NOW WE HAVE THE CORRECT PAGE
	MOVEM GET			; SCAN FIRST LINE AGAIN
	MOVE INP,COMPNT
	SETZM LEV1			; NO ID ON LEVEL 1 YET
	PUSH P,[STRUCT]			; INIT LINK POINTER
	PUSHJ P,IDPARS			; GET AN IDENTIFIER
LLEV1:	MOVEI T,ID
	MOVEI TA,LEV1
	PUSHJ P,EQUAL			; TEST FOR EQUALITY
	JRST [	SKIPN LEV1
		JRST LEV1A		;   ID<LEV1 - ADD ID BEFORE BLOCK
		JRST ENDXRF]		;		OR END OF XREF
	JRST [	MOVE 4,LKSM
		JRST EQUL1]		;   ID=LEV1 - STILL ON SAME ID
	POP P,PT			;   ID>LEV1 - NEW ID GET LEVEL 1 PTR
LEV1C:	HRRZ 6,(PT)
	JUMPE 6,LEV1A			; END OF LIST - ADD NEW IDENTIFIER
	MOVEI TA,2(6)			; GET POINTER TO NEXT IDENTIFIER
	PUSHJ P,EQUAL
	JRST LEV1A			; ADD NEW ID BEFORE THIS BLOCK
	JRST [	HRRZ PT,(PT)
		JRST LEV1B]		; IDENTIFIER FOUND IN LIST
	HRRZ PT,(PT)
	JRST LEV1C			; CHECK NEXT ELEMENT OF LIST

LEV1B:	PUSH P,PT			; IDENTIFIER FOUND, SAVE LEVEL 1 PTR
	HLRZ PT,1(PT)			; GO DOWN ONE LEVEL
	HRRZ 6,(PT)			; AND FIND END OF LIST OF FILES
	JUMPE 6,LEV2A
	MOVEI PT,(6)
	JRST .-3

LEV2A:	MOVE 4,LKSM			; AND BRANCH TO LINK FILE BLOCK
	JRST LEV2B			; AT SAME LEVEL

LEV1A:	PUSHJ P,CREBLK			; CREATE A NEW BLOCK - ID PNTR IN T
	PUSH P,NEW			; SAVE NEW LEVEL 1 POINTER
	MOVE 1,(PT)			; LINK NEW BLOCK AT SAME LEVEL
LKSM:	HRRM NEW,(PT)
	HRLM PT,(NEW)
	HRRM 1,(NEW)
	HRLM NEW,(1)
	MOVEI PT,(NEW)
	MOVE 4,[HRLM NEW,1(PT)]		; LINK FILE BLOCK AT NEXT LEVEL
LEV2B:	MOVEI T,NAME			; CREATE BLOCK FOR FILE NAME
	PUSHJ P,CREBLK
	XCT 4				; LINK AT  LEVEL 2
	MOVEI PT,(NEW)
	MOVE 1,[XWD ID,LEV1]		; SAVE CURRENT LEVEL 1 IDENTIFIER
	BLT 1,LEV1+7
; KEEP ON BUILDING STRUCTURE

	CAIG CONV,"9"			; IS NEXT ELEMENT A NUMBER?
	CAIGE CONV,"0"
	JRST LEV3A			; NO 
	MOVEI 1,1(FR)			; YES - SAVE CURRENT LEVEL 3 POINTER
	PUSH P,1			; SAVE TO-BE-CREATED LEVEL 3 PNTR
	JRST NUL

LEV3A:	MOVE 4,[HRLM NEW,1(PT)]		; LINK BLOCK AT NEXT LEVEL
EQUL1:	PUSHJ P,IDPARS			; GET BLOCK NAME
	MOVEI T,ID
	PUSHJ P,CREBLK			; CREATE A BLOCK FOR IT
	XCT 4				; AND LINK IT AT LEVEL 3
	MOVEI PT,(NEW)
	PUSH P,PT			; SAVE CURRENT LEVEL 3 POINTER
NUL:	AOBJN FR,.+2			; CREATE A BLOCK FOR THE LINE NUMBERS
	PUSHJ P,GETCOR
	HRLM FR,1(PT)			; AND LINK AT NEXT LEVEL (3 OR 4)
	SETZM (FR)
	AOBJN FR,.+2
	PUSHJ P,GETCOR
	HRRZI PT,(FR)
	SETZM (PT)
	SETZM T
C2:	PUSHJ P,IDPARS			; GET NEXT NUMBER
	SKIPE ID
	JRST ENDLEV 			; IDENTIFIER 
	MOVE TA,NUMB
	CAIL TA,77777
	JRST ENDXRF			; FUNNY NUMBER - EOF 
	CAIN CONV,"#"
	MOVNS TA			; NEGATE LINE NUMBER IF DEFINITION
	JUMPN T,.+4
	AOBJN FR,.+2
	PUSHJ P,GETCOR
	AOS (PT)			; INCREMENT WORD COUNT
	XCT CTAB(T)
	TRC T,1
	JRST C2

CTAB:	HRLZM TA,(FR)
	HRRM TA,(FR)

ENDLEV:	POP P,PT			; RESTORE LEVEL THREE POINTER
	JRST LLEV1			; RETURN TO START NEXT LINE

ENDXRF:	MOVE P,[IOWD PLEN,PDL]		;FLUSH ENTIRE STACK
	JRST LOOP			;RETURN FOR NEXT FILE
; END OF STRUCTURE BUILDING - NOW WE OUTPUT IT

N←15;	FIELD WIDTH
M←14;	FIELD START
CNT←10;	LINE CHAR COUNT
LCT←7;	LINE NUMBER COUNT
LEN←6;	MAXIMUM LINE LENGTH

ENDFIL:	CLOSE 1,			;RELEASE LAST INPUT FILE
	SKIPN 1,OUTPNT
	MOVEI 1,DEFOUT
	ENTER 1,(1)			;CREATE OUTPUT FILE
	JRST [	OUTSTR CRLF
		OUTSTR [ASCIZ .COULD NOT ENTER OUTPUT FILE.]
		CALLI 12]
	MOVEI BUFRS
	MOVEM JOBFF
	OUTBUF 1,NBUF
	SKIPN PT,STRUCT
	JRST DONE
	MOVEI LEN,=120
	SKIPE SHORT
	MOVEI LEN,=70			;MAXIMUM LINE LENGTH
	SETZM M				; INIT FIELD START
	MOVEI N,=10			; AND FIELD WIDTH
	MOVE [PUSHJ P,GLBCHK]		;INIT GLOBAL TEST
	SKIPN GLBAL
	MOVE [SKIPA]			; IF REQUESTED
	SKIPE LOCAL
	MOVE [PUSHJ P,LOCCHK]		; INIT LOCAL TEST
	MOVEM TEST#
	SETZM CNT			; INIT CHARACTER COUNT
	PUSHJ P,OUTLPT			;CALL OUTPUT ROUTINE
DONE:	RELEASE 1,			;END OF LISTING
GCLOOP:	MOVE 1,SVJOB			;SET CORE BACK TO INITIAL VALUE
	MOVEM 1,JOBFF
	CALLI 1,11
	HALT
	JRST GCREF
; RECURSIVE OUTPUT ROUTINE
; EACH CALL OUTPUTS A LIST AT ONE LEVEL

OUTLPT:	XCT TEST		; DO SELECTION TEST
	JRST NXTBLK		; FAILED - GET NEXT BLOCK
	MOVEI CONV," "		;FILL IN BLANKS TO COLUMN M
	CAIL CNT,(M)		;OTHERWISE THIS IS AN ID BLOCK
	JRST OL1
	PUSHJ P,PCHAR
	JRST .-3

OL1:	HLRZ 5,1(PT)		;GET POINTER TO NEXT LOWER LEVEL
	JUMPE 5,LINOUT		;NONE- THIS IS A LINE NUMBER BLOCK
	MOVEI T,2(PT)		;POINTER TO IDENTIFIER NAME
	MOVEI TA,-1(N)		;LEAVE AT LEAST ONE BLANK AFTER NAME
	PUSHJ P,OUTID		;PUT IT IN THE LINE
	PUSH P,TEST		;STACK PARAMATERS FOR RECURSION
	PUSH P,M
	PUSH P,N
	PUSH P,PT
	MOVE [SKIPA]
	MOVEM TEST
	ADDI M,(N)		;SET UP FOR NEXT LEVEL
	MOVEI N,=8
	MOVEI PT,(5)
	PUSHJ P,OUTLPT		;AND CALL AGAIN FOR NEXT LEVEL
	POP P,PT		;ALL LOWER LEVELS DONE, RESTORE
	POP P,N
	POP P,M
	POP P,TEST
NXTBLK:	HRRZ PT,(PT)		;GET NEXT BLOCK ON THIS LEVEL
	JUMPN PT,OUTLPT		;AND RETURN TO PROCESS
	POPJ P,			;IF ZERO, WE ARE DONE AT THIS LEVEL

LINOUT:	HRRZ LCT,1(PT)		;THIS IS A LINE NUMBER BLOCK-GET WORD COUNT
	PUSH P,PT		;SAVE POINTER
	MOVEI PT,1(PT)		;POINT AT FIRST WORD-1 OF LINE NUMBER
	SETZM 3			;INIT HALF WORD
OL3:	JUMPN 3,.+3
	AOS PT			;INDEX TO NEXT WORD IF READY FOR LEFT HALF
	SOJL LCT,OL4		;DONE
	XCT LOAD(3)		;LOAD PROPER HALF WORD
	TRC 3,1			;SWITCH HALVES
	JUMPE 4,OL4		;IF ZERO, DONE
	MOVEI 1,(CNT)		;COMPUTE CHAR COUNT AT END OF OUTPUT
	ADDI 1,(N)
	CAIG 1,(LEN)
	JRST OL2
	MOVEI CONV,15		;OUTPUT CRLF
	PUSHJ P,PCHAR
	MOVEI CONV,12
	PUSHJ P,PCHAR
	SETZM CNT		;CLEAR LINE COUNT
	MOVEI CONV," "		;AND SPACE TO PROPER COLUMN
	CAIL CNT,(M)
	JRST OL2
	PUSHJ P,PCHAR
	JRST .-3

LOAD:	HLRE 4,(PT)
	HRRE 4,(PT)

OL2:	MOVE CONV,4
	PUSHJ P,CONVRT		;OUTPUT LINE NUMBER
	JRST OL3		;RETURN FOR NEXT LINE NUMBER

OL4:	POP P,PT		;RESTORE POINTER
	MOVEI CONV,15		;END OF LINE NUMBER - OUTPUT CRLF
	PUSHJ P,PCHAR
	MOVEI CONV,12
	PUSHJ P,PCHAR
	SETZM CNT
	JRST NXTBLK		;RETURN FOR NEXT BLOCK ON THIS LEVEL

;IDENTIFIER OUTPUT ROUTINE
;POINTER TO COUNT IN T
;MAXIMUM COUNT IN TA
;OUTPUTS MINIMUM OF TWO COUNTS TO LPT
;USES AC 1

OUTID:	CAML TA,(T)
	MOVE TA,(T)		;GET SMALLER COUNT
	MOVE 1,[POINT 7,0]	;SET UP BYTE POINTER
	HRRI 1,1(T)
	ILDB CONV,1
	PUSHJ P,PCHAR
	SOJG TA,.-2
	POPJ P,
; GET ONE PART OF FILE SPECS
; SIXBIT PUT INTO SNAM
; ASCII ADDED TO NAME THROUGH POINTER IN 2
; EXPECT POINTER TO INPUT BUFFER IN 1
; LEAVES BREAK CHARACTER IN 4
; SKIPS BLANKS

GETPAR:	MOVE 3,[POINT 6,SNAM]
	SETZM SNAM
GETCHR:	ILDB 4,1
	CAIN 4," "
	JRST GETCHR
	CAIL 4,"0"
	CAILE 4,"9"
	SKIPA
	JRST .+4
	CAIL 4,"A"
	CAILE 4,"Z"
	POPJ P,
	IDPB 4,2
	MOVEI 4,-40(4)
	IDPB 4,3
	JRST GETCHR

;GET ONE CHARACTER FROM INPUT BUFFER
;RETURN IT IN CONV
;BRANCH TO EOF IF END OF FILE ON DISK SEEN

GCHAR:	SOSG IBUF+2
	IN 1,
	SKIPA
	JRST DSKERR
	ILDB CONV,IBUF+1
	POPJ P,

;PUT ONE CHARACTER IN OUTPUT BUFFER
;IT IS IN CONV

PCHAR:	SOSG OBUF+2
	OUT 1,
	SKIPA
	JRST DERR
	IDPB CONV,OBUF+1
	AOS CNT				;INDEX CHAR COUNT
	POPJ P,

DSKERR:	STATZ 1,20000
	JRST [	SETOM CONV		;EOF-RETURN NEG. CHAR
		POPJ P,]
DERR:	OUTSTR CRLF
	OUTSTR [ASCIZ .DISK ERROR.]
	CALLI 12
; MAGIC DECIMAL CONVERSION ROUTINE 
; N DIGIT OUTPUT WITH LEAD ZEROS SUPPRESSED
; # AFTER NUMBER IF IT WAS NEGATIVE
; NUMBER IN CONV ON ENTRY
; WILL NOT PRINT ZERO !!
; USES AC T AND TA AND 1


CONVRT:	MOVM T,CONV
	SKIPGE CONV
	JRST	[PUSH P,["#"]
		JRST .+2]
	PUSH P,[" "]
	MOVEI 1,-1(N)		;FINAL CHAR COUNTS TOO
	SETZM SUP#
	PUSHJ P,CONV1
	POP P,CONV
	PUSHJ P,PCHAR
	POPJ P,

CONV1:	JUMPE T,[MOVEI CONV," "	;RECURSIVE DECIMAL OUTPUT ROUTINE
		PUSHJ P,PCHAR	;SUPPRESS LEAD ZEROS
		SOJG 1,$.-1
		POPJ P,]
	IDIVI T,=10
	MOVEI TA,60(TA)		;CONVERT DIGIT TO STRING
CONV2:	HRLM TA,(P)		;STACK CHARACTER FOR OUTPUT
	SOJLE 1,.+2
	PUSHJ P,CONV1
	HLRZ CONV,(P)
	JRST PCHAR

; CORE GETTING ROUTINE AND ERROR OUTPUT
; UPDATES FR
; USES AC 1

GETCOR:	MOVE 1,JOBREL
	ADDI 1,2000
	CALLI 1,11
	JRST NOCORE
	HRLI FR,-2000
	POPJ P,

NOCORE:	OUTSTR CRLF
	OUTSTR [ASCIZ .NO FREE CORE.]
	CALLI 12
; STRING EQUALITY TEST
; FIRST STRING POINTER IN T
; SECOND IN TA
; RETURNS IF T<TA
; SKIPS 1 IF T=TA
; SKIPS 2 IF T>TA
; USES ACS 1-5
; DOES NOT ALTER T AND TA

EQUAL:	MOVE 1,(T)		;GET CHARACTER COUNTS FOR STRINGS
	MOVE 3,(TA)
	MOVE 2,[POINT 7,0]	;SET UP BYTE POINTERS TO STRINGS
	MOVE 4,2
	HRRI 2,1(T)
	HRRI 4,1(TA)
	SETZM 5
	SETZM 6
ELOOP:	SOJL 1,E1		;TEST COUNTS FOR END OF STRING
	SOJL 3,E2		;TEST BEFORE COMPARE IN CASE OF NULL STRING
	ILDB 5,2		;GET NEXT PAIR OF CHARACTER
	ILDB 6,4
	CAIGE 5,(6)
	POPJ P,			;COMPARE LOW - T<TA
	CAIG 5,(6)
	JRST ELOOP		;COMPARE EQUAL - TEST NEXT PAIR OF CHARS
	JRST GREAT		;COMPARE GREATER - T>TA

E1:	SOS 3			;END OF STRING 1 - ALIGN STRING 2
E2:	CAMGE 1,3		;END OF STRING 2 - 1 ALREADY ALIGNED
	POPJ P,			;STRING 1 SHORTEST
	CAME 1,3
GREAT:	AOS (P)			;STRING 2 SHORTEST
	AOS (P)			;STRINGS OF EQUAL LENGTH
	POPJ P,

;TEST FOR GLOBAL (OR LOCAL) IDENTIFIER (ON LEVEL 1 ONLY)
;SKIPS IF GLOBAL (OR LOCAL)
;USES AC 1

GLBCHK:	HLRZ 1,1(PT)		;GET LIST OF FILE NAMES
	HRRZ 1,(1)
	SKIPE 1
	AOS (P)			; GLOBAL IF MORE THAN ONE
	POPJ P,

LOCCHK:	HLRZ 1,1(PT)		;GET LIST OF FILE NAMES
	HRRZ 1,(1)
	SKIPN 1
	AOS (P)			; LOCAL IF ONLY ONE
	POPJ P,
; CREATE A NEW IDENTIFIER BLOCK
; POINTER TO IDENTIFIER IN T, WHICH IS DESTROYED
; LEAVES POINTER TO BLOCK IN NEW
; USES AC 1-3

CREBLK:	AOBJN FR,.+2			;GET FIRST WORD
	PUSHJ P,GETCOR
	MOVEI NEW,(FR)			;SAVE POINTER
	SETZM (NEW)			;CLEAR BLOCK POINTERS
	AOBJN FR,.+2			;GET SECOND WORD
	PUSHJ P,GETCOR
	MOVE 2,(T)			;GET CHARACTER COUNT
	ADDI 2,5			;FOR COUNT WORD
	IDIVI 2,5
	SKIPE 3
	ADDI 2,1			;WORD COUNT FOR IDENTIFIER
	MOVEM 2,(FR)
	AOBJN FR,.+2			;STORE CHAR COUNT AND ID
	PUSHJ P,GETCOR
	MOVE 3,(T)
	MOVEM 3,(FR)
	AOS T
	SOJG 2,.-5
	POPJ P,

; TEST FILE SPECIFIED TO MAKE SURE IT EXISTS

LOOKFL:	HRLI 3,-3(FR)
	HRRI 3,LBLK
	BLT 3,LBLK+3
	LOOKUP 1,LBLK
	JRST	[SETOM ERROR		; FILE DOES NOT EXIST - SET FLAG
		OUTSTR CRLF
		OUTSTR [ASCIZ .NO SUCH FILE - .]
		SETZM 6			; AND TELL HIM NOW RATHER THAN
		IDPB 6,2		; AFTER TEN MINUTES OF PROCESSING
		OUTSTR NAME		; THE PREVIOUS FILES
		POPJ P,]
	POPJ P,

LBLK:	BLOCK 4
; THIS IS THE MAGIC 6-STATE, TABLE DRIVEN, INPUT PARSER
; STATE IS IN ST
; OUTPUT IS IN ID, IF IDENTIFIER, NUMB IF NUMBER
; RETURNS WITH CONV CONTAINING BREAK CHAR, 0 IF IDENT. WAS TOO LONG
; IF ID IS ZERO, RETURNING NUMBER; OTHERWISE, ID IS COUNT WITH IDENT.
;   STARTING IN ID+1
; USES AC 1

IDPARS:	MOVEI ST,2			;INIT TO PARSE IDENTIFIERS
PARSE:	SKIPN CONV,SVBRK#		; USE BREAK CHAR IF SAVED
GET:	HALT				; CALLING PROGRAM INITS INPUT
	SETZM SVBRK			; BREAK BAD HERE
	JUMPL CONV,DSKEOF		; THIS IS DISK EOF
	ANDI CONV,177			; DISPATCH ON CHARACTER
	JRST @(CONV)TAB

; BRANCHES FROM INPUT SCANNER TABLE

GOODTS:	POP P,(P)		;FLUSH RETURN
	MOVE [XWD LFATB,T3+2]	;SET CODE TO SWITCH INPUT AT NEXT LF
	BLT T3+5
	SETZM SVBRK
	JRST TSTOK		;AND PASS TEST

FAIL2:	POP P,(P)		;FLUSH RETURN
	JRST P2			;WE ARE AT NEXT PAGE

BRKA:	SKIPN CCNT		;NULL LINE ILLEGAL AS FIRST LINE
	JRST FAILTS
BRK:	AOS CCNT		;INDEX CHARACTER COUNT
	SKIPL ID
	JRST GET		;RETURN ONLY IF IDENTIFIER FOUND
	MOVEI =10*5+1		;COMPUTE CHAR COUNT
	ADDM ID
POPLAB:	POPJ P,			;ALSO USED FOR IMMEDIATE RETURNS

PROC:	SKIPN ID		;PROCESS IDENTIFIER IN TEST MODE
	JRST [SKIPE FID
	      JRST $.+3
	      SKIPE CCNT	; FIRST
	      JRST FAILTS	; IDENTIFIER SHOULD START AT FIRST CHAR
	      AOS FID
	      MOVNI =10*5+1	;  START OF ID IF NO COUNT
	      MOVEM ID		;   STORE - MAX COUNT TO STOP LOOP
	      MOVE 1,[POINT 7,ID+1]
	      JRST .+1]
	AOSL ID			;INCREMENT COUNT
	JRST BRK		;RETURN IF IDENT. TOO LONG
	IDPB CONV,1		;STORE NEXT CHAR
	JRST GET
; MORE BRANCHES FOR INPUT SCANNER

BADCHR:	OUTSTR CRLF		;ILLEGAL CHARACTER FOUND
	OUTSTR [ASCIZ .ILLEGAL CHARACTER:.]
	OUTCHR CONV
	OUTSTR [ASCIZ . FOUND IN FILE .]
	OUTSTR NAME+1
	JRST ENDXRF		;START NEXT FILE

STBRK:	MOVEI ST,5		;START BREAK SCAN
	JRST GET

BRKSAV:	MOVEM CONV,SVBRK	;BREAK, SAVE, AND RETURN
BRKRET:	SKIPL ID
	POPJ P,
	MOVEI =10*5+1		;BREAK AND RETURN
	ADDM ID			;FIXUP ID COUNT IF IDENTIFIER
	POPJ P,

STNUM:	SETZM ID		;START PROCESSING NUMBER
	MOVEI ST,4
	SUBI CONV,60
	MOVEM CONV,NUMB
	JRST GET

ADDNUM:	MOVE 1,NUMB		;ADD TO NUMBER
	IMULI 1,=10
	SUBI CONV,60
	ADDI 1,(CONV)
	MOVEM 1,NUMB
	JRST GET

STID:	MOVNI =10*5+1		;START IDENTIFIER PROCESSING
	MOVEM ID
	MOVE 1,[POINT 7,ID+1]
	MOVEI ST,3
ADDID:	AOSL ID			;ADD TO IDENTIFIER
	JRST [SETZM CONV	;ID OVERFLOWED
	      JRST BRK]
	IDPB CONV,1
	JRST GET

SETGET:	MOVE P10		;FIXUP INPUT AND LINE FEED DISPATCH
	MOVEM GET
	SETZM SVBRK
	MOVE [XWD LFTAB,T3+2]
	BLT T3+5
	JRST @T3(ST)

ZCHAR:	CAILE ST,2		;ZERO CHARACTER FOUND - DISK EOF
	OUTSTR [ASCIZ .NOT A CREF FILE !!!.]
	JRST ENDXRF
; STILL MORE BRANCHES

FAILTS:	POP P,(P)		;FLUSH RETURN
	MOVE P10		;SET INPUT TO READ FROM DISK
	MOVEM GET
	JRST TSTFAL		;AND FAIL TEST

DSKEOF:	CAILE ST,2
	JRST BRKSAV		; 3-5 BREAK, SAVE, AND RETURN
	JRST ZCHAR		; 0-2 TERMINATE THIS FILE
; PRIMARY TABLE FOR INPUT SCANNER

TAB:	20,,T6				;NULL CHAR
	REPEAT =8,{ST+20,,T1}
	ST+20,,T2			;TAB
	ST+20,,T3			;LINE FEED
 	ST+20,,T1
	ST+20,,T4			;FORM FEED
	ST+20,,T5			;CARRIAGE RETURN
	REPEAT =18,{ST+20,,T1}
	ST+20,,T2			;SPACE
	REPEAT 2,{ST+20,,T1}
	ST+20,,T7			;#
	ST+20,,T10			;$
	REPEAT =9,{ST+20,,T1}
	ST+20,,T10			;.
	ST+20,,T1
	REPEAT =10,{ST+20,,T9}		;DIGITS
	REPEAT 7,{ST+20,,T1}
	REPEAT =26,{ST+20,,T10}		;CAPITAL LETTERS
	REPEAT 6,{ST+20,,T1}
	REPEAT =26,{ST+20,,T10}		;SMALL LETTERS
	REPEAT 5,{ST+20,,T1}

; SECONDARY TABLES FOR SCANNER
; STATES ARE:
;	0	SCANNING FIRST LINE TESTING FOR CORRECT PAGE
;	1	SCANNING FOR FORM FEED
;	2	SCANNING FOR IDENTIFIER OR NUMBER
;	3	SCANNING IDENTIFIER
;	4	SCANNING NUMBER
;	5	SCANNING FOR BREAK CHARACTERS

;	INVALID CHARACTERS

T1:	FAILTS		;0-FAIL TEST
	GET		;1-IGNORE
	REPEAT 4,{BADCHR} ;2-5 ILLEGAL

;	TAB AND SPACE

T2:	BRK		;0-BREAK
	GET		;1-IGNORE
	GET		;2-IGNORE
	STBRK		;3-START BREAK
	STBRK		;4-START BREAK
	GET		;5-IGNORE

;	NULL CHAR - DISK EOF OR END OF BUFFER IN ALL STATES

T6:	GET		;IGNORE
; MORE SECONDARY TABLES
;	LINE FEED

T3:	GOODTS		;0-END OF TEST
	GET		;1-IGNORE
	GET		;2-IGNORE
	STBRK		;3-START BREAK
	STBRK		;4-START BREAK
	GET		;5-IGNORE

;	FORM FEED

T4:	FAIL2		;0-FAIL TEST
	POPLAB		;1-FF FOUND
	GET		;2-IGNORE
	STBRK		;3-START BREAK
	STBRK		;4-START BREAK
	GET		;5-IGNORE

;	CARRIAGE RETURN

T5:	BRKA		;0-BREAK
	REPEAT 5,{GET}	;1-5 IGNORE

;	#

T7:	BRK		;0-BREAK
	GET		;1-IGNORE
	BADCHR		;2-ILLEGAL
	BADCHR		;3-ILLEGAL
	BRKRET		;4-BREAK AND RETURN
	BADCHR		;5-ILLEGAL

;	DIGITS

T9:	BRK		;0-BREAK
	GET		;1-IGNORE
	STNUM		;2-START PROCESSING NUMBER
	ADDID		;3-ADD TO IDENTIFIER
	ADDNUM		;4-ADD TO NUMBER
	BRKSAV		;5-BREAK, RETURN, AND SAVE

;	PERIOD AND LETTERS

T10:	PROC		;0-PROCESS IDENTIFIER
	GET		;1-IGNORE
	STID		;2-START PROCESSING IDENTIFIER
	ADDID		;3-ADD TO IDENTIFIER
	BADCHR		;4-ILLEGAL
	BRKSAV		;5-BREAK, RETURN, AND SAVE
; FINISH WITH SOME VARIABLES

PDL:	BLOCK PLEN		;PUSH DOWN LIST
DEFOUT:	SIXBIT .GCREF.		;DEFAULT OUTPUT FILE
	SIXBIT .LST.
	0
	0
COMPNT:	POINT 7,COMBUF
COMBUF:	BLOCK =30		;COMMAND BUFFER
SNAM:	BLOCK =5		;SIXBIT NAME
NAME:	BLOCK =5		;ASCIZ NAME (OF DISK FILE)
DEFEXT:	SIXBIT .LST.		;DEFAULT EXTENTION
DEFPPN:	0			;DEFAULT PPN
OBUF:	BLOCK 3
IBUF:	BLOCK 3
BUFRS:	BLOCK NBUF*204		;HERE ARE OUR BUFFERS
CRLF:	ASCIZ .
.
ID:	BLOCK =10		;CURRENT IDENTIFIER
NUMB:	0			;CURRENT NUMBER
LEV1:	BLOCK =10		;TOP LEVEL IDENTIFIER
SHORT:	0			;NON-ZERO IF SHORT LISTING WANTED
LOCAL:	0			;NON-ZERO IF ONLY LOCALS WANTED
GLBAL:	0			;NON-ZERO IF ONLY GLOBALS WANTED
INPNT:	0			;POINTS TO LIST OF INPUT FILES
STRUCT:	0			;POINTS TO START OF DATA STRUCTURE
ERROR:	0			;NON-ZERO FOR COMMAND ERROR
OUTPNT:	0			;POINTS TO OUTPUT FILE NAME
CCNT:	0			;CHARACTER COUNT FOR PAGE TESTING
FID:	0			;NUMBER OF IDENTIFIERS SEE SO FAR THIS LINE
LFATB:	REPEAT 4,{JRST SETGET}
LFTAB:	GET
	STBRK
	STBRK
	GET

	LIT			; FORCE ALLOCATION OF LITERALS AND VARIABLES
	VAR
FREE:				;HERE IS OUR FREE STORAGE
				; NO CODE BEYOND THIS ADDESS
	END GCREF-2